//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#ifndef __ELASTOS_INTERLOCK_H__
#define __ELASTOS_INTERLOCK_H__

INLINE Int32 InterlockedExchangeAdd(PInt32 pAddend, Int32 increment)
{
    Int32 lOriginalAddend;

    ASM(__LOCK
        "xadd   %%eax, (%%edx);"
        :"=a"(lOriginalAddend)
        :"a"(increment), "d"(pAddend));

    return lOriginalAddend;
}

INLINE Int32 InterlockedExchange(PInt32 pTarget, Int32 value)
{
    Int32 lOriginalTarget;

    ASM(__LOCK
        "xchg   %%eax, (%%edx);"
        :"=a"(lOriginalTarget)
        :"a"(value), "d"(pTarget));

    return lOriginalTarget;
}

INLINE PVoid InterlockedExchangePointer(PVoid *pTarget, PVoid value)
{
    PVoid pvOriginalTarget;

    ASM(__LOCK
        "xchg   %%eax, (%%edx);"
        :"=a"(pvOriginalTarget)
        :"a"(value), "d"(pTarget));

    return pvOriginalTarget;
}

INLINE Int32 InterlockedCompareExchange(PInt32 destination,
                Int32 exchange, Int32 comperand)
{
    Int32 lOriginalDestination;

    ASM(__LOCK
        "cmpxchg    %%ecx, (%%edx);"
        :"=a"(lOriginalDestination)
        :"a"(comperand), "c"(exchange), "d"(destination));

    return lOriginalDestination;
}

INLINE PVoid InterlockedCompareExchangePointer(PVoid *pDestination,
                PVoid exchange, PVoid comperand)
{
    PVoid pvOriginalDestination;

    ASM(__LOCK
        "cmpxchg    %%ecx, (%%edx);"
        :"=a"(pvOriginalDestination)
        :"a"(comperand), "c"(exchange), "d"(pDestination));

    return pvOriginalDestination;
}

INLINE Int32 IterlockedIncrement(PInt32 pAddend)
{
    Int32 lIncrementedAddend;

    ASM("movl   $1, %%eax;"
        __LOCK
        "xadd   %%eax, (%%edx);"
        "inc    %%eax;"
        :"=a"(lIncrementedAddend)
        :"d"(pAddend));

    return lIncrementedAddend;
}

INLINE Int32 InterlockedDecrement(PInt32 pAddend)
{
    Int32 lDecrementedAddend;

    ASM("movl   $-1, %%eax;"
        __LOCK
        "xadd   %%eax, (%%edx);"
        "dec    %%eax;"
        :"=a"(lDecrementedAddend)
        :"d"(pAddend));

    return lDecrementedAddend;
}

#endif //__ELASTOS_INTERLOCK_H__
